home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
comm
/
misc
/
xqsrc931030.lzh
/
library
/
address.c
next >
Wrap
C/C++ Source or Header
|
1993-01-29
|
21KB
|
929 lines
/*
* Name: address.c
*
* Description: Routines for address manipulation
*
* Copyright: 1992-1993 by David Jones.
*
* Distribution:
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
*
* The Free Software Foundation David Jones
* 675 Mass Ave 6730 Tooney Drive
* Cambridge, MA Orleans, Ontario
* 02139 K1C 6R4
* USA Canada
*
* Usenet: gnu@prep.ai.mit.edu dej@qpoint.ocunix.on.ca
* Fidonet: 1:163/109.8
*
* $Log: $
*
*/
#include <exec/types.h>
#include <string.h>
#include "xferq.h"
#include "xferqint.h"
#include "xferq_pragmas.h"
#include <utility/hooks.h>
#include <proto/utility.h>
char *DefaultDomain, *DefaultZone, *DefaultPoint;
void InitAddress(void)
/*
* Does: Initializes the default address values. These are hard-coded
* now, but will be read from a file eventually.
*/
{
DefaultDomain = CopyString("Fidonet");
DefaultZone = CopyString("1");
DefaultPoint = CopyString("0");
}
struct NetAddress *GetTextAddress(char **strp)
/*
* In: strp Pointer to string to convert
*
* Does: Attempts to convert an address in TEXT form.
*/
{
char *p, *oldp;
struct NetAddress *na;
char *temp;
/*
* First character must be a caret.
*/
p = *strp;
if (*p++ != '^') {
return NULL;
}
oldp = p;
/*
* Anything goes for content.
*/
if (!GetAddrElement(&p, TRUE)) {
return NULL;
}
/*
* OMS needs a null-terminated string so make one.
*/
temp = CopyStringN(oldp, p - oldp);
if (!temp) {
return NULL;
}
/*
* Create final address.
*/
na = AllocObject(0, XQO_ADDRESS);
if (na) {
na->type = XQNT_TEXT;
na->addr.text = temp;
*strp = p;
}
else {
XfqDropObject(temp);
}
return na;
}
struct NetAddress *GetUucpAddress(char **strp)
/*
* In: strp Pointer to string to convert
*
* Does: Attempts to convert an address in UUCP form.
*/
{
char *p, *oldp;
struct NetAddress *na;
char *temp;
p = *strp;
oldp = p;
/*
* Machine name must be non-numeric and no periods!
*/
if (GetAddrElement(&p, FALSE) != ET_ALPHA) {
return NULL;
}
/*
* OMS needs a null-terminated string so make one.
*/
temp = CopyStringN(oldp, p - oldp);
if (!temp) {
return NULL;
}
/*
* Create final address.
*/
na = AllocObject(0, XQO_ADDRESS);
if (na) {
na->type = XQNT_UUCP;
na->addr.machine = temp;
*strp = p;
}
else {
XfqDropObject(temp);
}
return na;
}
struct NetAddress *GetFqdaAddress(char **strp)
/*
* In: strp Pointer to string to convert
*
* Does: Attempts to convert an address in FQDA form.
*/
{
char *p, *oldp;
struct NetAddress *na;
char *temp;
p = *strp;
oldp = p;
while (TRUE) {
/*
* Each component must be non-numeric and no periods!
*/
if (GetAddrElement(&p, FALSE) != ET_ALPHA) {
return NULL;
}
/*
* If parse stopped at a period, then go for more.
*/
if (*p != '.') {
break;
}
p++;
}
/*
* OMS needs a null-terminated string so make one.
*/
temp = CopyStringN(oldp, p - oldp);
if (!temp) {
return NULL;
}
/*
* Create final address.
*/
na = AllocObject(0, XQO_ADDRESS);
if (na) {
na->type = XQNT_FQDA;
na->addr.fqda = temp;
*strp = p;
}
else {
XfqDropObject(temp);
}
return na;
}
struct NetAddress *GetFidoAddress(char **strp, struct NetAddress *base,
int mand, int opt)
/*
* In: strp Pointer to string to parse
* base Base address to use as model
* mand Mandatory flags
* opt Optional flags
*
* Does: Attempts to parse a Fidonet address.
*/
{
char preDelim, postDelim;
struct NetAddress *na;
char *p, *oldp, *elem;
int type;
postDelim = 0;
p = *strp;
if (base) {
na = DupObject(base);
}
else {
na = AllocObject(0, XQO_ADDRESS);
}
if (!na) {
return NULL;
}
na->type = XQNT_FIDO;
opt &= XQADDR_FIDO;
mand &= XQADDR_FIDO;
while (TRUE) {
preDelim = postDelim;
oldp = p;
type = GetAddrElement(&p, FALSE);
postDelim = *p;
if (!type) {
XfqDropObject(na);
return NULL;
}
elem = CopyStringN(oldp, p - oldp);
if (opt == XQADDR_DOMAIN || postDelim == '#' || preDelim == '@') {
/*
* domain
*
* Replace the domain name, dropping old one if necessary.
* If element type is illegal, then the DropObject(na) drops
* the new element too.
*/
XfqDropObject(na->addr.fido.domain);
na->addr.fido.domain = elem;
if (type != ET_ALPHA || !(opt & XQADDR_DOMAIN)) {
XfqDropObject(na);
return NULL;
}
mand &= ~XQADDR_DOMAIN;
if (postDelim == '#') {
p++;
}
else {
break;
}
}
else if (opt == XQADDR_ZONE || postDelim == ':') {
/* zone */
XfqDropObject(na->addr.fido.zone);
na->addr.fido.zone = elem;
if (type != ET_NUMBER || !(opt & XQADDR_ZONE)) {
XfqDropObject(na);
return NULL;
}
mand &= ~XQADDR_ZONE;
if (postDelim == ':') {
p++;
}
else {
break;
}
}
else if (opt == XQADDR_NET || postDelim == '/' || preDelim == ':') {
/* net */
XfqDropObject(na->addr.fido.net);
na->addr.fido.net = elem;
if (type != ET_NUMBER || !(opt & XQADDR_NET)) {
XfqDropObject(na);
return NULL;
}
mand &= ~XQADDR_NET;
if (postDelim == '/') {
p++;
}
else {
break;
}
}
else if (opt == XQADDR_NODE || preDelim == '/') {
/* node */
XfqDropObject(na->addr.fido.node);
na->addr.fido.node = elem;
if (type != ET_NUMBER || !(opt & XQADDR_NODE)) {
XfqDropObject(na);
return NULL;
}
mand &= ~XQADDR_NODE;
if (postDelim == '.' || postDelim == '@') {
p++;
}
else {
break;
}
}
else if (opt == XQADDR_POINT || preDelim == '.') {
/* point */
XfqDropObject(na->addr.fido.point);
na->addr.fido.point = elem;
if (type != ET_NUMBER || !(opt & XQADDR_POINT)) {
XfqDropObject(na);
return NULL;
}
mand &= ~XQADDR_POINT;
if (postDelim == '@') {
p++;
}
else {
break;
}
}
else {
XfqDropObject(na);
return NULL;
}
}
/* end of address */
if (mand) {
XfqDropObject(na);
return NULL;
}
else {
*strp = p;
CanonAddress(na);
return na;
}
}
struct NetAddress *__saveds __asm LIBGetAddress(register __a0 char *string,
register __a1 struct NetAddress *addr,
register __a2 struct TagItem *tags)
/*
* In: string A0 Pointer to string to convert
* addr A1 Template for converted address
* tags A2 Taglist controlling operation
*
* Does: Replaces the elements of addr with new values based on the
* input string. The user flags indicate which types of input
* are valid, and may be used to resolve ambiguous situations.
*
* Valid tags are:
* XQ_EndPos Write a pointer to the first illegal char
* into data field.
* XQ_Mandatory Data is bitset of mandatory fields
* XQ_Optional Data is bitset of optional fields
* XQ_SpaceDelim TRUE if spaces are permitted.
*/
{
struct NetAddress *na;
int mand, opt;
char *p, *oldp, *atp;
char **endPos;
BOOL spaceDelim;
char *userName;
ULONG *errp;
mand = GetTagData(XQ_Mandatory, 0, tags);
opt = GetTagData(XQ_Optional, 0, tags);
spaceDelim = GetTagData(XQ_SpaceDelim, TRUE, tags);
/*
* atp holds pointer to stuff after username.
*/
p = string;
userName = NULL;
oldp = p;
if (GetAddrElement(&p, TRUE) == ET_ALPHA) {
/*
* Got what might be a user name. If next char is '@' then
* make the user name.
*/
atp = p;
if (spaceDelim && *p == ' ') {
atp++;
}
if (*atp == '@') {
userName = CopyStringN(oldp, p - oldp);
if (!userName) {
return NULL;
}
atp++;
if (spaceDelim && *atp == ' ') {
atp++;
}
}
}
if (!userName) {
atp = string;
}
na = NULL;
p = atp;
if (addr) {
switch (addr->type) {
case XQNT_FIDO:
na = GetFidoAddress(&p, addr, mand, opt);
break;
case XQNT_UUCP:
na = GetUucpAddress(&p);
break;
case XQNT_FQDA:
na = GetFqdaAddress(&p);
break;
case XQNT_TEXT:
na = GetTextAddress(&p);
break;
}
}
if (!na) {
if (opt & XQADDR_FIDO) {
p = atp;
na = GetFidoAddress(&p, addr, mand, opt);
}
if (!na && (opt & XQADDR_MACHINE)) {
p = atp;
na = GetUucpAddress(&p);
}
if (!na && (opt & XQADDR_FQDA)) {
p = atp;
na = GetFqdaAddress(&p);
}
if (!na && (opt & XQADDR_TEXT)) {
p = atp;
na = GetTextAddress(&p);
}
}
if (na) {
na->userName = userName;
}
else {
errp = PeekError();
if (*errp != XQERROR_NOMEM) {
*errp = XQERROR_BADADR;
}
XfqDropObject(userName);
}
endPos = (char **)GetTagData(XQ_EndPos, NULL, tags);
if (endPos) {
*endPos = p;
}
SetErrorTags(tags);
return na;
}
LONG StrAECmp(char *left, char *right)
/*
* In: left, right Pointers to items to compare
*
* Does: Compares two address elements and returns less/greater/equal.
*/
{
if (!left) {
return (right != NULL);
}
else if (!right) {
return 1;
}
else {
return Stricmp(left, right);
}
}
LONG NumAECmp(char *left, char *right)
/*
* In: left, right Pointers to items to compare
*
* Does: Compares two numeric address elements and returns delta.
*/
{
LONG nleft, nright;
nleft = nright = 0;
if (left) {
GetNumber(left, 10, 5, &nleft);
}
if (right) {
GetNumber(right, 10, 5, &nright);
}
return nleft - nright;
}
LONG SimpleCmpAddress(struct NetAddress *left, struct NetAddress *right,
int mand)
/*
* In: left, right Pointers to addresses to compare
* mand Bit mask of mandatory items
*
* Does: Compares two addresses and returns a delta based on the
* difference.
*/
{
LONG delta;
delta = left->type - right->type;
if (delta) {
return delta;
}
switch (left->type) {
case XQNT_UUCP:
return StrAECmp(left->addr.machine, right->addr.machine);
case XQNT_FQDA:
return StrAECmp(left->addr.fqda, right->addr.fqda);
case XQNT_TEXT:
return StrAECmp(left->addr.text, right->addr.text);
case XQNT_FIDO:
if (mand & XQADDR_DOMAIN) {
delta = StrAECmp(left->addr.fido.domain, right->addr.fido.domain);
if (delta) {
return delta;
}
}
if (mand & XQADDR_ZONE) {
delta = NumAECmp(left->addr.fido.zone, right->addr.fido.zone);
if (delta) {
return delta;
}
}
if (mand & XQADDR_NET) {
delta = NumAECmp(left->addr.fido.net, right->addr.fido.net);
if (delta) {
return delta;
}
}
if (mand & XQADDR_NODE) {
delta = NumAECmp(left->addr.fido.node, right->addr.fido.node);
if (delta) {
return delta;
}
}
if (mand & XQADDR_POINT) {
return NumAECmp(left->addr.fido.point, right->addr.fido.point);
}
return 0;
}
}
LONG __saveds __asm LIBCmpAddress(register __a0 void *left,
register __a1 void *right,
register __a2 struct TagItem *tags)
/*
* In: left A0 "Left" address or session
* right A1 "Right" address or session
* tags A2 Taglist controlling operation
*
* Does: Compares left and right. Returns:
* >0 if left > right
* 0 if left = right
* <0 if left < right
*
* Either left or right may be a session; in this case equality
* is returned if any address in left is equivalent to any address
* in right.
*
* Valid tags are:
* XQ_Mandatory Indicates fields that are to be used in
* comparison (default all).
*/
{
int mand,result;
mand = GetTagData(XQ_Mandatory, XQADDR_ALLBUTUSER, tags);
result = SimpleCmpAddress(left, right, mand);
return result;
}
struct NetAddress *__saveds __asm LIBMap(
register __a0 struct NetAddress *addr,
register __a1 struct TagItem *tags)
/*
* In: addr A0 Address to map
* tags A1 Taglist controlling operation
*
* Does: Applies maps according to the tags to return a new address.
* Valid tags are:
* XQ_MapForward Apply the map in the forward direction
* XQ_MapReverse Apply the map in the reverse direction
*/
{
return NULL;
}
ULONG __saveds __asm LIBFilter(register __a0 void *object,
register __a1 struct TagItem *tags)
/*
* In: object A0 Address or session to filter
* tags A1 Taglist controlling operation
*
* Does: Tests the session or address against the filter condition.
* Returns TRUE if it passes, FALSE otherwise. Valid tags are:
*
* XQ_MapForward Test against the left part of a map.
* XQ_MapReverse Test against the right part of a map.
* XQ_Filter Test against a filter
* XQ_Inclusive If TRUE, all objects in the session must pass
* the filter. Otherwise, only one need pass.
*/
{
return FALSE;
}
char *SimplePutAddress(struct NetAddress *na, int mand, int opt,
BOOL spaceDelim)
/*
* In: na Address to print
* mand Bit mask of mandatory fields
* opt Bit mask of optional fields
* spaceDelim TRUE to insert spaces in Fido
*
* Does: Creates a string and puts the given address in it.
*/
{
char *str;
int adrLen;
int partLen;
str = AllocObject(20, XQO_STRING);
if (!str) {
return NULL;
}
*str = '\0';
adrLen = 0;
if (na->userName) {
partLen = strlen(na->userName);
str = NeedString(str, partLen + 4); /* make room for ' @ ' */
if (!str) {
return NULL;
}
strcpy(str, na->userName);
adrLen = partLen;
if (na->addr.machine || na->addr.fqda || na->addr.text ||
na->addr.fido.domain || na->addr.fido.zone ||
na->addr.fido.net || na->addr.fido.node || na->addr.fido.point) {
if (na->type == XQNT_FIDO && spaceDelim) {
strcpy(str + adrLen, " @ ");
adrLen += 3;
}
else {
strcpy(str + adrLen, "@");
adrLen++;
}
}
}
switch (na->type) {
case XQNT_TEXT:
partLen = strlen(na->addr.text);
str = NeedString(str, partLen + 2);
if (str) {
str[partLen] = '^';
strcpy(str + adrLen, na->addr.text);
}
return str;
case XQNT_FQDA:
partLen = strlen(na->addr.fqda);
str = NeedString(str, partLen + 1);
if (str) {
strcpy(str + adrLen, na->addr.fqda);
}
return str;
case XQNT_UUCP:
partLen = strlen(na->addr.machine);
str = NeedString(str, partLen + 1);
if (str) {
strcpy(str + adrLen, na->addr.machine);
}
return str;
case XQNT_FIDO:
/*
* Determine which fields to print out. mand's bits are set
* to indicate which fields must be printed.
*/
if (opt & XQADDR_DOMAIN && na->addr.fido.domain &&
Stricmp(na->addr.fido.domain, DefaultDomain)) {
mand |= XQADDR_DOMAIN;
}
if (opt & XQADDR_ZONE && na->addr.fido.zone &&
Stricmp(na->addr.fido.zone, DefaultZone)) {
mand |= XQADDR_ZONE;
}
if (opt & XQADDR_NET && na->addr.fido.net &&
Stricmp(na->addr.fido.net, "0") &&
Stricmp(na->addr.fido.net, "-1")) {
mand |= XQADDR_NET;
}
if (opt & XQADDR_NODE && na->addr.fido.node &&
Stricmp(na->addr.fido.node, "0") &&
Stricmp(na->addr.fido.node, "-1")) {
mand |= XQADDR_NODE;
}
if (opt & XQADDR_POINT && na->addr.fido.point &&
Stricmp(na->addr.fido.point, "0")) {
mand |= XQADDR_POINT;
}
if (opt & XQADDR_ATDOMAIN && na->addr.fido.domain &&
Stricmp(na->addr.fido.domain, DefaultDomain)) {
mand |= XQADDR_ATDOMAIN;
}
/*
* Protection: don't attempt to output fields that don't exist.
*/
if (!na->addr.fido.domain) {
mand &= ~(XQADDR_DOMAIN | XQADDR_ATDOMAIN);
}
if (!na->addr.fido.zone) {
mand &= ~XQADDR_ZONE;
}
if (!na->addr.fido.net) {
mand &= ~XQADDR_NET;
}
if (!na->addr.fido.node) {
mand &= ~XQADDR_NODE;
}
if (!na->addr.fido.point) {
mand &= ~XQADDR_POINT;
}
/*
* Print required fields.
*/
if (mand & XQADDR_DOMAIN) {
partLen = strlen(na->addr.fido.domain);
str = NeedString(str, partLen + 2);
if (!str) {
return NULL;
}
strcpy(str + adrLen, na->addr.fido.domain);
adrLen += partLen;
if (mand & (XQADDR_ZONE | XQADDR_NET)) {
str[adrLen++] = '#';
}
}
if (mand & XQADDR_ZONE) {
partLen = strlen(na->addr.fido.zone);
str = NeedString(str, partLen + 2);
if (!str) {
return NULL;
}
strcpy(str + adrLen, na->addr.fido.zone);
adrLen += partLen;
if (mand & XQADDR_NET) {
str[adrLen++] = ':';
}
}
if (mand & XQADDR_NET) {
partLen = strlen(na->addr.fido.net);
str = NeedString(str, partLen + 2);
if (!str) {
return NULL;
}
strcpy(str + adrLen, na->addr.fido.net);
adrLen += partLen;
if (mand & XQADDR_NODE) {
str[adrLen++] = '/';
}
}
if (mand & XQADDR_NODE) {
partLen = strlen(na->addr.fido.node);
str = NeedString(str, partLen + 2);
if (!str) {
return NULL;
}
strcpy(str + adrLen, na->addr.fido.node);
adrLen += partLen;
if (mand & XQADDR_POINT) {
str[adrLen++] = '.';
}
}
if (mand & XQADDR_POINT) {
partLen = strlen(na->addr.fido.point);
str = NeedString(str, partLen + 2);
if (!str) {
return NULL;
}
strcpy(str + adrLen, na->addr.fido.point);
adrLen += partLen;
if (mand & XQADDR_ATDOMAIN) {
str[adrLen++] = '@';
}
}
if (na->addr.fido.domain && (mand & XQADDR_ATDOMAIN)) {
partLen = strlen(na->addr.fido.domain);
str = NeedString(str, partLen + 2);
if (!str) {
return NULL;
}
strcpy(str + adrLen, na->addr.fido.domain);
}
}
return str;
}
struct PutAddrData {
struct Hook hook;
char **array;
char *line;
struct NetAddress *last;
struct NetAddress *diff;
short lineSize, mand, opt;
BOOL delta, spaceDelim;
};
BOOL __asm PutSessAddress(register __a0 struct Hook *hook,
register __a2 struct NetAddress *addr,
register __a1 struct TagItem *tags)
/*
* In: hook A0 Pointer to hook/data structure
* addr A2 Pointer to address to print
* tags A1 Tag list passed to PutAddress (not used)
*
* Does: Writes one address of the session into the array.
*/
{
return FALSE;
}
char *__saveds __asm LIBPutAddress(register __a0 void *object,
register __a1 struct TagItem *tags)
/*
* In: object A0 Pointer to address/session to output
* tags A1 Taglist controlling operation
*
* Does: Returns a string containing a printable form of the address.
* Valid tags are:
*
* XQ_Mandatory Data is fields that must be printed
* XQ_Optional Data is fields that are printed if nonempty
* XQ_LineSize This tag is used when a session is passed in.
* All addresses in the session are output in
* a single string whose maximum length is given
* by this tag. Function returns array of these
* strings.
* XQ_Delta If TRUE, then the differences between the
* current and previous addresses are used in
* determining if optional fields should be output.
* XQ_SpaceDelim If TRUE, then spaces are output around '@'
* separating user name and Fidonet address.
*/
{
struct PutAddrData pad;
char *str;
pad.mand = GetTagData(XQ_Mandatory, 0, tags);
pad.opt = GetTagData(XQ_Optional, 0, tags);
pad.spaceDelim = GetTagData(XQ_SpaceDelim, TRUE, tags);
if (ObjectType(object) == XQO_ADDRESS) {
str = SimplePutAddress(object, pad.mand, pad.opt, pad.spaceDelim);
SetErrorTags(tags);
return str;
}
/*
else {
pad.delta = GetTagData(XQ_Delta, FALSE, tags);
pad.lineSize = GetTagData(XQ_LineSize, 79, tags);
if (pad.delta) {
pad.diff = AllocObject(XQO_ADDRESS, NULL);
if (!pad.diff) {
return NULL;
}
}
pad.hook.h_Entry = PutSessAddress;
pad.last = NULL;
pad.array = NULL;
pad.line = NULL;
XfqWalkSessionCallBackTags(object,
XQ_CallBack, &pad.hook,
TAG_DONE);
SetErrorTags(tags);
return (char *)pad.array;
} */
Error(XQERROR_BADOBJECT);
return NULL;
}
BOOL CanonAddress(struct NetAddress *na)
/*
* In: na User-supplied address
*
* Does: This function is a kludge that ensures that addresses conform
* to certain style guidelines for queue files. The function
* returns an address derived from the given address through the
* following transformations:
*
* FIDO z:n/f -> Fidonet#z:n/f.0
*/
{
if (na->type == XQNT_FIDO) {
if (!na->addr.fido.domain || !strcmp(na->addr.fido.domain, "")) {
na->addr.fido.domain = XfqCopyObject(DefaultDomain);
}
if (!na->addr.fido.zone || !strcmp(na->addr.fido.zone, "")) {
na->addr.fido.zone = XfqCopyObject(DefaultZone);
}
if (!na->addr.fido.point || !strcmp(na->addr.fido.point, "")) {
na->addr.fido.point = XfqCopyObject(DefaultPoint);
}
}
return TRUE;
}